package com.flybook.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.flybook.common.utils.StringUtils;
import com.flybook.system.domain.SysNotice;
import com.flybook.web.controller.tool.FlyBookInfo;
import com.lark.oapi.Client;
import com.lark.oapi.core.request.RequestOptions;
import com.lark.oapi.service.contact.v3.model.BatchGetIdUserReq;
import com.lark.oapi.service.contact.v3.model.BatchGetIdUserReqBody;
import com.lark.oapi.service.contact.v3.model.BatchGetIdUserResp;
import com.lark.oapi.service.contact.v3.model.UserContactInfo;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.*;

@Component
@Configuration
public class FlyBookUtils {
//    @Autowired

    public String TENANT_ACCESS_TOKEN_URL = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";
    public String BATCH_GET_ID_URL = "https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id";
    public String WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/94cb0728-be8d-4ae8-9c56-cc6598a3c511";
    public String UPLOAD_IMG_URL = "https://open.feishu.cn/open-apis/im/v1/images";

    @Value("${feiShuParam.appId}")
    private String appId;
    // 令牌秘钥
    @Value("${feiShuParam.appSecret}")
    private String appSecret;
    private RestTemplate restTemplate;


    public boolean SendToMsg(SysNotice notice, FlyBookInfo flyBookInfo) throws Exception {
        if (Objects.equals(notice.getNoticeState(), "text")) {
            return SendToText(notice, flyBookInfo);
        } else if (Objects.equals(notice.getNoticeState(), "post")) {
            return SendForMarkDown(notice, flyBookInfo);
        }
        return false;
    }

    /**
     * 发送文本消息
     *
     * @param notice
     * @return
     * @throws Exception
     */
    public boolean SendToText(SysNotice notice, FlyBookInfo flyBookInfo) throws Exception {
        JSONObject json = new JSONObject();
        JSONObject body = new JSONObject();
        Long timestamp = Instant.now().getEpochSecond();
        String sign = GenSign(timestamp, notice.getNoticeSecret());
        String msg = "";
        if (Objects.equals(notice.getNoticeType(), 2) && StringUtils.isNotEmpty(notice.getNoticeMobiles())) {
            System.out.println("lai le ");
            JSONArray userIds = getUserId(notice.getNoticeMobiles());
            StringBuilder at = new StringBuilder();
            for (Object id : userIds) {
                at.append("<at user_id=\"").append(id.toString()).append("\"></at> ");
            }
            msg += at;
            msg += flyBookInfo.getContent();
        } else {
            msg += "<at user_id=\"all\"></at> " + flyBookInfo.getContent();
        }

        json.put("text", msg);
        body.put("sign", sign);
        body.put("timestamp", timestamp.toString());
        body.put("msg_type", "text");
        body.put("content", json.toString());
        restTemplate = new RestTemplate();

        HttpEntity<String> entity = new HttpEntity<>(body.toString());
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        ResponseEntity<String> response = restTemplate.postForEntity(WEBHOOK_URL, entity, String.class);
        String responseBody = new String(response.getBody().getBytes(), StandardCharsets.UTF_8);
        JSONObject jsonResult = JSON.parseObject(responseBody);
        return Objects.equals(jsonResult.getString("code"), "0");
    }

    /**
     * 发送富文本消息
     *
     * @param notice
     * @return
     * @throws Exception
     */
    public boolean SendForMarkDown(SysNotice notice, FlyBookInfo flyBookInfo) throws Exception {
        JSONObject json = new JSONObject();
        JSONObject body = new JSONObject();
        Long timestamp = Instant.now().getEpochSecond();
        String sign = GenSign(timestamp, notice.getNoticeSecret());
        JSONArray userIds = getUserId(notice.getNoticeMobiles());
//        System.out.println(openid);
        Map<String, Object> postContent = new HashMap<>();
        Map<String, Object> post = new HashMap<>();
        postContent.put("zh_cn", generatePostContent(notice.getNoticeMobiles(), flyBookInfo.getContent()));
        post.put("post", postContent);
        body.put("sign", sign);
        body.put("timestamp", timestamp.toString());
        body.put("msg_type", "post");
        body.put("content", post);
        restTemplate = new RestTemplate();

        HttpEntity<String> entity = new HttpEntity<>(body.toString());
        System.out.println("发送消息内容");
        System.out.println(body);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        ResponseEntity<String> response = restTemplate.postForEntity(WEBHOOK_URL, entity, String.class);
        String responseBody = new String(response.getBody().getBytes(), StandardCharsets.UTF_8);
        JSONObject jsonResult = JSON.parseObject(responseBody);
        System.out.println("发送消息返回");
        System.out.println(jsonResult);
        return Objects.equals(jsonResult.getString("code"), "0");
    }

    private Map<String, Object> generatePostContent(String mobiles, String content) throws Exception {
        Map<String, Object> title = new HashMap<>();
        title.put("tag", "text");
        title.put("text", "项目有更新: ");
        Map<String, Object> link = new HashMap<>();
        link.put("tag", "a");
        link.put("text", "请查看");
        link.put("href", "http://www.example.com/");
        Map<String, Object> atUser = new HashMap<>();
        atUser.put("tag", "at");
        JSONArray userIds = getUserId(mobiles);
        for (Object id : userIds) {
            atUser.put("user_id", id);
        }

        List<Map<String, Object>> contentList = new ArrayList<>();
        Object[] externalArray = new Object[1];//循环改这
        contentList.add(title);
        contentList.add(link);
        contentList.add(atUser);

        externalArray[0] = contentList;
        Map<String, Object> postContent = new HashMap<>();
        postContent.put("title", "项目更新通知，测试富文本消息");
        postContent.put("content", externalArray);
        return postContent;
    }

    /**
     * 获取用户id
     *
     * @param mobile
     * @return
     * @throws Exception
     */
    private JSONArray getUserId(String mobile) throws Exception {
        String[] mobiles = mobile.split(",");

        String tenant_access_token = getTenantAccessToken();
        Client client = Client.newBuilder(appId, appSecret).build();
        BatchGetIdUserReq req = BatchGetIdUserReq.newBuilder().userIdType("open_id").batchGetIdUserReqBody(BatchGetIdUserReqBody.newBuilder().mobiles(mobiles).build()).build();
        // 发起请求
        BatchGetIdUserResp resp = client.contact().user().batchGetId(req, RequestOptions.newBuilder().tenantAccessToken(tenant_access_token).build());

        if (resp.success()) {
            UserContactInfo[] userContactInfos = resp.getData().getUserList();
            JSONArray jsonArr = new JSONArray();
            for (UserContactInfo info : userContactInfos) {
                if (StringUtils.isNotEmpty(info.getUserId())) {
                    jsonArr.add(info.getUserId());
                }
            }
            return jsonArr;
        }
        return null;
    }

    /**
     * 自建应用获取 tenant_access_token
     *
     * @return
     */
    private String getTenantAccessToken() {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json; charset=utf-8");
        headers.set("Accept-Charset", "utf-8");
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("app_id", appId);
        params.add("app_secret", appSecret);
        restTemplate = new RestTemplate();

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);

        ResponseEntity<String> response = restTemplate.postForEntity(TENANT_ACCESS_TOKEN_URL, entity, String.class);
        String responseBody = new String(response.getBody().getBytes(), StandardCharsets.UTF_8);
        JSONObject jsonResult = JSON.parseObject(responseBody);
        if (Objects.equals(jsonResult.getString("code"), "0")) {
            return jsonResult.getString("tenant_access_token");
        }
        return "";
    }

    /**
     * 获取签名
     *
     * @param timestamp
     * @param secret
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public String GenSign(long timestamp, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        String stringToSign = timestamp + "\n" + secret;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(new byte[]{});

        return new String(Base64.encodeBase64(signData));
    }
}
